#pragma once
#include <iostream>
#include <pthread.h>
#include <cstdio>
#include <queue>
#include <vector>
#include <semaphore.h>
#define MAX 10

template <class T>
class queue_cond
{
public:
    queue_cond()
    {
        sem_init(&_sem_size, 0, 10);
        sem_init(&_data_size, 0, 0);
        _task.resize(MAX);
        pthread_mutex_init(&_mutex, nullptr);
    }

    void push(T& task)
    {
        product(_data_size);
        _task[_product_step++] = task;
        _product_step %= MAX;
        consumer(_sem_size);
    }

    T& pop()
    {
        product(_sem_size);
        task& data = _task[_consumer_step];
        ++_consumer_step %= MAX;
        consumer(_data_size);
        return data;
    }

    ~queue_cond()
    {
        pthread_mutex_destroy(&_mutex);
        sem_destroy(&_data_size);
        sem_destroy(&_sem_size);
    }

private:
    void product(sem_t &sem)
    {
        sem_post(&sem);
    }

    void consumer(sem_t &sem)
    {
        sem_wait(&sem);
    }

private:
    sem_t _data_size;
    sem_t _sem_size;
    pthread_mutex_t _mutex;
    std::vector<T> _task;
    size_t _consumer_step = 0;
    size_t _product_step = 0;
};